<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    canvas {
      width: 100vw;
      height: 100vh;
      display: block;
      background-color: #f2d32d;
    }
  </style>
  <canvas id="c"></canvas>
  <body></body>

  <script>
    function setRectangle(gl, x, y, width, height) {
      var x1 = x
      var x2 = x + width
      var y1 = y
      var y2 = y + height
      gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]),
        gl.STATIC_DRAW
      )
    }

    // 创建着色器方法，输入参数：渲染上下文，着色器类型，数据源
    function createShader(gl, type, source) {
      var shader = gl.createShader(type) // 创建着色器对象
      gl.shaderSource(shader, source) // 提供数据源
      gl.compileShader(shader) // 编译 -> 生成着色器
      var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS)
      if (success) {
        return shader
      }

      console.log(gl.getShaderInfoLog(shader))
      gl.deleteShader(shader)
    }

    function createProgram(gl, vertexShader, fragmentShader) {
      var program = gl.createProgram()
      gl.attachShader(program, vertexShader)
      gl.attachShader(program, fragmentShader)
      gl.linkProgram(program)
      var success = gl.getProgramParameter(program, gl.LINK_STATUS)
      if (success) {
        return program
      }

      console.log(gl.getProgramInfoLog(program))
      gl.deleteProgram(program)
    }

    var image = new Image()
    image.src = './test.png' // 必须在同一域名下
    image.onload = function () {
      render(image)
    }
    function render(img) {
      const canvas = document.getElementById('c')
      const gl = canvas.getContext('webgl')

      const vertexShaderSource = `
        attribute vec2 position;
        attribute vec2 a_texCoord;

        uniform vec2 u_resolution;

        varying vec2 v_texCoord;

        void main() {
            // convert the rectangle from pixels to 0.0 to 1.0
            vec2 zeroToOne = position / u_resolution;
            // convert from 0->1 to 0->2
            vec2 zeroToTwo = zeroToOne * 2.0;
            vec2 clipSpace = zeroToTwo - 1.0;

            gl_Position = vec4(clipSpace * vec2(1, -1),0,1); 
            v_texCoord = a_texCoord;
        }
    `

      const fragmentShaderSource = `
        precision mediump float;
        uniform sampler2D u_image;
        varying vec2 v_texCoord;
        void main() {
            gl_FragColor = texture2D(u_image, v_texCoord);
        }
    `

      const vertexShader = createShader(
        gl,
        gl.VERTEX_SHADER,
        vertexShaderSource
      )
      const fragmentShader = createShader(
        gl,
        gl.FRAGMENT_SHADER,
        fragmentShaderSource
      )
      console.log(vertexShader, image.width, '查看数据')
      // Link the two shaders into a program
      const program = createProgram(gl, vertexShader, fragmentShader)

      // 找到纹理所在的位置
      const textureAttributeLocation = gl.getAttribLocation(
        program,
        'a_texCoord'
      )
      const texcoordBuffer = gl.createBuffer()
      gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer)
      gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([
          0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
        ]),
        gl.STATIC_DRAW
      )

      // 找到属性所在的位置
      const positionAttributeLocation = gl.getAttribLocation(
        program,
        'position'
      )
      // 属性值 从是从缓冲去拿的  创建一个缓冲
      const positionBuffer = gl.createBuffer()
      // 绑定点
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
      setRectangle(gl, 0, 0, image.width, image.height)

      // 设置贴图
      const texture = gl.createTexture()
      gl.bindTexture(gl.TEXTURE_2D, texture)

      // Set the parameters so we can render any size image.
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

      // Upload the image into the texture.
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)

      // 设置视口
      gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
      // 清除canvas
      gl.clearColor(0, 0, 0, 0)
      gl.clear(gl.COLOR_BUFFER_BIT)

      // 使用哪一个着色器语言
      gl.useProgram(program)

      // 告诉webgl 准备从之前的缓冲获取数据给着色器的属性
      gl.enableVertexAttribArray(positionAttributeLocation)
      // 将绑定点绑定到缓冲数据（positionBuffer）
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
      // 告诉属性怎么从positionBuffer中读取数据 (ARRAY_BUFFER)
      const size = 3 // 每次迭代运行提取两个单位数据  {x:0,y:0,z:0,w :1}
      const type = gl.FLOAT // 每个单位的数据类型是32位浮点型
      const normalize = false // 不需要归一化数据
      const stride = 0 // 0 = 移动单位数量 * 每个单位占用内存（sizeof(type)）
      // 每次迭代运行运动多少内存到下一个数据开始点
      const offset = 0 // 从缓冲起始位置开始读取
      gl.vertexAttribPointer(
        positionAttributeLocation,
        size,
        type,
        normalize,
        stride,
        offset
      )

      // 创建纹理
      gl.enableVertexAttribArray(textureAttributeLocation)
      gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer)
      gl.vertexAttribPointer(
        textureAttributeLocation,
        size,
        type,
        normalize,
        stride,
        offset
      )

      const resolutionLocation = gl.getUniformLocation(program, 'u_resolution')
      gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height)

      // draw
      gl.drawArrays(gl.TRIANGLES, 0, 6)
    }
  </script>
</html>
